package com.tanjun.gateway.gatewayservice.config;

import cn.dev33.satoken.stp.StpInterface;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.tanjun.common.enums.RedisCacheEnum;
import com.tanjun.common.enums.user.UserTypeEnum;
import com.tanjun.common.exception.BizException;
import com.tanjun.common.model.R;
import com.tanjun.userservice.apiservice.api.AdminMenuApi;
import com.tanjun.userservice.apiservice.api.AdminUserApi;
import com.tanjun.userservice.apiservice.response.adminmenu.admin.AdminMenuResponse;
import com.tanjun.userservice.apiservice.response.adminrole.admin.AdminRoleResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.redis.core.ReactiveRedisTemplate;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * sat-token获取用户角色和权限接口
 */
@Component
public class SaTokenRoleAndPremissionConfig implements StpInterface {
    @Autowired
    @Lazy
    private AdminUserApi adminUserApi;
    @Autowired
    @Lazy
    private AdminMenuApi adminMenuApi;
    @Autowired
    private ReactiveRedisTemplate<String,Object> redisTemplate;

    @Override
    public List<String> getPermissionList(Object loginId, String loginType) {
        String permissionKey=StrUtil.format(RedisCacheEnum.USER_PERMISSION.getKey(),loginId,loginType);
        List<String> listPermission= (List<String>) redisTemplate.opsForValue().get(permissionKey).block();
        if(CollUtil.isNotEmpty(listPermission)){
            return listPermission;
        }
        UserTypeEnum roleTypeEnum= UserTypeEnum.valueFrom(loginType);
        if (Objects.requireNonNull(roleTypeEnum) == UserTypeEnum.ADMIN) {
            R<List<AdminRoleResponse>> rRoles = adminUserApi.getUserRoles(Long.valueOf(loginId.toString()));
            if (rRoles.isSuccess() && CollectionUtil.isNotEmpty(rRoles.getData())) {
                List<Long> roleIds = rRoles.getData().stream().map(AdminRoleResponse::getRoleId).distinct().collect(Collectors.toList());
                R<List<AdminMenuResponse>> rMenus = adminMenuApi.getRolesMenus(roleIds);
                if (CollectionUtil.isNotEmpty(rMenus.getData())) {
                    List<String> list= rMenus.getData()
                            .stream()
                            .map(AdminMenuResponse::getPerm)
                            .filter(StrUtil::isNotEmpty)
                            .toList();
                    redisTemplate.opsForValue().set(permissionKey,list, Duration.ofSeconds(RedisCacheEnum.USER_PERMISSION.getExpire())).block();
                    return list;
                }
            }
        }
        return Collections.emptyList();
    }

    @Override
    public List<String> getRoleList(Object loginId, String loginType) {
        String roleKey=StrUtil.format(RedisCacheEnum.USER_ROLE.getKey(),loginId,loginType);
        List<String> listRole= (List<String>) redisTemplate.opsForValue().get(roleKey).block();
        if(CollUtil.isNotEmpty(listRole)){
            return listRole;
        }
        UserTypeEnum roleTypeEnum= UserTypeEnum.valueFrom(loginType);
        switch (roleTypeEnum){
            case ADMIN:
                R<List<AdminRoleResponse>> rRoles= adminUserApi.getUserRoles(Long.valueOf(loginId.toString()));
                if(CollectionUtil.isNotEmpty(rRoles.getData())){
                    List<String> list= rRoles.getData()
                            .stream()
                            .map(AdminRoleResponse::getRoleCode)
                            .filter(StrUtil::isNotEmpty)
                            .toList();
                    redisTemplate.opsForValue()
                            .set(roleKey,list,Duration.ofSeconds(RedisCacheEnum.USER_ROLE.getExpire())).block();
                }
                return Collections.emptyList();
            case MEM:
                return Collections.singletonList("mem");
            default:
                throw new BizException("用户角色有误");
        }

    }


    public void clearCache(Object loginId, String loginType) {
        String roleKey=StrUtil.format(RedisCacheEnum.USER_ROLE.getKey(),loginId,loginType);
        String permissionKey=StrUtil.format(RedisCacheEnum.USER_PERMISSION.getKey(),loginId,loginType);
        redisTemplate.delete(roleKey,permissionKey).block();
    }


}
